import java.io.*;

public class LogAnalysis {

    // 背书节点日志标记
    String flagEndorserStart = "Entering: request from";    // 1、开始背书。验证交易提案中的信息：创建者签名、通道、ACL、链码信息等
    String flagEndorserTxSimulator = "NewTxSimulator";      // 2、执行模拟交易：构造模拟提案、加载链码配置、操作容器、执行链码等
    String flagEndorserSign1 = "SimulateProposal";
    String flagEndorserSign2 = "Exit";                      // 3、背书交易：构造背书提案、签名等
    String flagEndorserEnd = "Exit: request from";          // 4、背书完成。

    // 提交节点日志标记
    String flagCommiterStart = "VerifyBlock";                                   // 1、开始验证区块
    String flagCommiterValidateRW = "StoreBlock -\\u003e INFO";                 // 2、验证读写集
    String flagCommiterValidateState = "Validating state for block";            // 验证前的准备
    String flagCommiterUpdateStateDB = "transactions to state database";        // 3、更新状态数据库
    String flagCommiterUpdateHistoryDB = "transactions to history database";    // 4、更新历史数据 库
    String flagCommiterCommittedBlock = "CommitWithPvtData -\\u003e INFO";      // 5、提交区块到账本

    // 排序节点日志标记
    String flagOrdererEnqueueStart = "Enqueuing message into batch";
    String flagOrdererEnqueueEnd = "Broadcast has successfully enqueued message";
    String flagOrdererCreatedBlock = "Proposed block";
    String flagOrdererWroteBlock = "Wrote block";

    String logFilePath = "/home/cy/Documents/ATL/docs/开发工作/Fabric性能实验/logs/tx8-BL-endorser/endorser.log";
    String outputFilePath = "/home/cy/Documents/ATL/docs/开发工作/Fabric性能实验/logs/tx8-BL-endorser/output.log";

    public static void main(String[] args) {
        new LogAnalysis().loadLogFile();
    }

    private static String START_FLAG = "09:";
    private static String END_FLAG = " CST";

    public void loadLogFile() {
        try {
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(logFilePath)));
            BufferedReader in = new BufferedReader(new InputStreamReader(bis, "utf-8"), 10 * 1024 * 1024);
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(outputFilePath)));
            BufferedWriter out = new BufferedWriter(new OutputStreamWriter(bos, "utf-8"), 1024);
            String strTime = null;
            String[] subStrTime = null;
            String line = null;

            long timeEndorserStart = 0L;
            long timeEndorserTxSimulator = 0L;
            long timeEndorserSign = 0L;
            long timeEndorserEnd = 0L;

            long timeCommiterStart = 0L;
            long timeCommiterValidateRW = 0L;
            long timeCommiterValidateState = 0L;
            long timeCommiterUpdateStateDB = 0L;
            long timeCommiterUpdateHistoryDB = 0L;
            long timeCommiterCommittedBlock = 0L;

            float totalTimeEndorserPrepare = 0F;
            float totalTimeEndorserTxSimulate = 0F;
            float totalTimeEndorserSign = 0F;

            float totalTimeCommiterPrepare = 0F;
            float totalTimeCommiterValidateBlock = 0F;
            float totalTimeCommiterValidateState = 0F;
            float totalTimeCommiterUpdateState = 0F;
            float totalTimeCommiterUpdateHistory = 0F;

            float totalTx = 0F;
            float totalTimeOrder = 0F;

            int i = 0;
            int j = 0;

            while (in.ready()) {
                line = in.readLine();

                if (line.contains(flagEndorserStart)) {
                    strTime = line.substring(line.indexOf(START_FLAG), line.indexOf(END_FLAG));
                    timeEndorserStart = timeToMillis(strTime);
                    out.write(line);
                    out.newLine();

//                } else if (line.contains(flagEndorserTxSimulator)) {
//                    strTime = line.substring(line.indexOf(START_FLAG), line.indexOf(END_FLAG));
//                    timeEndorserTxSimulator = timeToMillis(strTime);
//                } else if (line.contains(flagEndorserSign1) && line.contains(flagEndorserSign2)) {
//                    strTime = line.substring(line.indexOf(START_FLAG), line.indexOf(END_FLAG));
//                    timeEndorserSign = timeToMillis(strTime);
                } else if (line.contains(flagEndorserEnd)) {
//                    if (i < 2001 || i > 22000) {
//                        i++;
//                        continue;
//                    }
                    out.write(line);
                    out.newLine();

                    strTime = line.substring(line.indexOf(START_FLAG), line.indexOf(END_FLAG));
                    timeEndorserEnd = timeToMillis(strTime);
                    out.write("Endorser" + i + "======>\r\n");
//                    out.write("   背书-验证时间：" + (timeEndorserTxSimulator - timeEndorserStart) + "\r\n");
//                    out.write("背书-模拟交易时间：" + (timeEndorserSign - timeEndorserTxSimulator) + "\r\n");
//                    out.write("   背书-签名时间：" + (timeEndorserEnd - timeEndorserTxSimulator) + "\r\n");
                    out.write("   背书时间：" + (timeEndorserEnd - timeEndorserStart) + "\r\n");

//                    totalTimeEndorserPrepare += (timeEndorserTxSimulator - timeEndorserStart);
//                    totalTimeEndorserTxSimulate += (timeEndorserSign - timeEndorserTxSimulator);
//                    totalTimeEndorserSign += (timeEndorserEnd - timeEndorserTxSimulator);

                    System.out.println("Endorser" + i + "======>");
//                    System.out.println("   背书-验证时间：" + (timeEndorserTxSimulator - timeEndorserStart));
//                    System.out.println("背书-模拟交易时间：" + (timeEndorserSign - timeEndorserTxSimulator));
//                    System.out.println("   背书-签名时间：" + (timeEndorserEnd - timeEndorserTxSimulator));
                    System.out.println("   背书时间：" + (timeEndorserEnd - timeEndorserStart));
                    i++;

                } else if (line.contains(flagCommiterStart)) {
                    strTime = line.substring(line.indexOf(START_FLAG), line.indexOf(END_FLAG));
//                    System.out.println(line);
                    if ((timeToMillis(strTime) - timeCommiterStart) > 2000) {
                        totalTimeOrder += (timeToMillis(strTime) - timeCommiterStart);
//                        System.out.println((timeToMillis(strTime) - timeCommiterStart));
                    }
                    timeCommiterStart = timeToMillis(strTime);
                    out.write(line);
                    out.newLine();
//                } else if (line.contains(flagCommiterValidateRW)) {
//                    strTime = line.substring(line.indexOf(START_FLAG), line.indexOf(END_FLAG));
////                    System.out.println(line);
//                    timeCommiterValidateRW = timeToMillis(strTime);
//                }else if (line.contains(flagCommiterValidateState)) {
//                    strTime = line.substring(line.indexOf(START_FLAG), line.indexOf(END_FLAG));
//                    timeCommiterValidateState = timeToMillis(strTime);
////                    System.out.println(line);
//                } else if (line.contains(flagCommiterUpdateStateDB)) {
//                    strTime = line.substring(line.indexOf(START_FLAG), line.indexOf(END_FLAG));
//                    timeCommiterUpdateStateDB = timeToMillis(strTime);
////                    System.out.println(line);
//                } else if (line.contains(flagCommiterUpdateHistoryDB)) {
//                    strTime = line.substring(line.indexOf(START_FLAG), line.indexOf(END_FLAG));
//                    timeCommiterUpdateHistoryDB = timeToMillis(strTime);
                } else if (line.contains(flagCommiterCommittedBlock)) {
//                    if (j < 21 || j > 320) {
//                        j++;
//                        continue;
//                    }
//                    System.out.println(line);
                    strTime = line.substring(line.indexOf(START_FLAG), line.indexOf(END_FLAG));
                    timeCommiterCommittedBlock = timeToMillis(strTime);
                    out.write(line);
                    out.newLine();
                    out.write("Committer" + j + "======>\r\n");
//                    out.write("       提交-准备时间：" + (timeCommiterValidateRW - timeCommiterStart) + "\r\n");
//                    out.write("    提交-验证区块时间：" + (timeCommiterValidateState - timeCommiterValidateRW) + "\r\n");
//                    out.write("    提交-验证状态时间：" + (timeCommiterUpdateStateDB - timeCommiterValidateState) + "\r\n");
//                    out.write("提交-更新StateDB时间：" + (timeCommiterUpdateHistoryDB - timeCommiterUpdateStateDB) + "\r\n");
//                    out.write(" 提交-historyDB时间：" + (timeCommiterCommittedBlock - timeCommiterUpdateHistoryDB) + "\r\n");
                    out.write("        排序-总时间：" + (timeCommiterStart - timeEndorserEnd) + "\r\n");

//                    totalTimeOrder += (timeCommiterStart - timeEndorserEnd);
//                    totalTimeCommiterPrepare += (timeCommiterValidateRW - timeCommiterStart);
//                    totalTimeCommiterValidateBlock += (timeCommiterValidateState - timeCommiterValidateRW);
//                    totalTimeCommiterValidateState += (timeCommiterUpdateStateDB - timeCommiterValidateState);
//                    totalTimeCommiterUpdateState += (timeCommiterUpdateHistoryDB - timeCommiterUpdateStateDB);
//                    totalTimeCommiterUpdateHistory += (timeCommiterCommittedBlock - timeCommiterUpdateHistoryDB);

//                    totalTx += Integer.parseInt(line.substring(line.indexOf("] with ") + 7,line.indexOf(" transaction(s)")));


                    System.out.println("Committer" + j + "======>");
//                    System.out.println("       提交-准备时间：" + (timeCommiterValidateRW - timeCommiterStart));
//                    System.out.println("    提交-验证区块时间：" + (timeCommiterValidateState - timeCommiterValidateRW));
//                    System.out.println("    提交-验证状态时间：" + (timeCommiterUpdateStateDB - timeCommiterValidateState));
//                    System.out.println("提交-更新StateDB时间：" + (timeCommiterUpdateHistoryDB - timeCommiterUpdateStateDB));
//                    System.out.println(" 提交-historyDB时间：" + (timeCommiterCommittedBlock - timeCommiterUpdateHistoryDB));
                    System.out.println((timeCommiterStart - timeEndorserEnd));
                    j++;
                }
            }

            totalTimeEndorserPrepare /= 20000.0;
            totalTimeEndorserTxSimulate /= 20000.0;
            totalTimeEndorserSign /= 20000.0;

//            totalTimeOrder /= 300.0;
            totalTimeCommiterPrepare /= 300.0;
            totalTimeCommiterValidateBlock /= 300.0;
            totalTimeCommiterValidateState /= 300.0;
            totalTimeCommiterUpdateState /= 300.0;
            totalTimeCommiterUpdateHistory /= 300.0;

            out.write("各阶段平均时间： \r\n");
            out.write("       背书-验证时间：" + totalTimeEndorserPrepare + "\r\n");
            out.write("    背书-模拟交易时间：" + totalTimeEndorserTxSimulate + "\r\n");
            out.write("       背书-签名时间：" + totalTimeEndorserSign + "\r\n");
//            out.write("         排序-总时间：" + totalTimeOrder + "\r\n");
            out.write("       提交-准备时间：" + totalTimeCommiterPrepare + "\r\n");
            out.write("    提交-验证区块时间：" + totalTimeCommiterValidateBlock + "\r\n");
            out.write("    提交-验证状态时间：" + totalTimeCommiterValidateState + "\r\n");
            out.write("提交-更新StateDB时间：" + totalTimeCommiterUpdateState + "\r\n");
            out.write(" 提交-historyDB时间：" + totalTimeCommiterUpdateHistory + "\r\n");
            out.write("   提交-区块平均间隔：" + totalTimeOrder + "\r\n");
            out.write("     区块中平均交易数：" + totalTx/300 + "\r\n");

            bos.flush();
            out.flush();
            in.close();
            bis.close();
            out.close();
            bos.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public long timeToMillis(String time) {
        String[] subStrTime = time.substring(0, time.indexOf('.')).split(":");
        long t1 = Integer.parseInt(subStrTime[0]);
        long t2 = Integer.parseInt(subStrTime[1]);
        long t3 = Integer.parseInt(subStrTime[2]);
        long t4 = Integer.parseInt(time.substring(time.indexOf('.') + 1));
        return t4 + t3 * 1000 + t2 * 60 * 1000 + t1 * 60 * 60 * 1000;
    }
}
